﻿#include "TcpClient_T.h"

#include <utility>

#include "TcpClient_T_Private.h"

using namespace ZTcp;

TcpClient_T::TcpClient_T(QObject *parent, bool useTaskPool, qintptr socketDescriptor)
    : QObject(parent),
      p_(nullptr),
      tcpClienPrivateThread_(),
      waitDataTrans_(new QWaitCondition{}),
      waitDataTransMutex_(new QMutex{}) {
  // 初始化私有
  p_ = new TcpClient_T_Private{socketDescriptor, useTaskPool, waitDataTrans_};

  // 连接数据写入到处理现场
  connect(this, &TcpClient_T::sigWrite, p_, &TcpClient_T_Private::slotWrite, Qt::QueuedConnection);
  connect(this, &TcpClient_T::sigWritePtr, p_, &TcpClient_T_Private::slotWritePtr, Qt::QueuedConnection);
  // 连接启动
  connect(this, &TcpClient_T::sigStart, p_, &TcpClient_T_Private::slotStart);

  // 连接启动完成
  connect(p_, &TcpClient_T_Private::sigStartDone, this, &TcpClient_T::sigStartDone);
  // 连接断开连接
  connect(p_, &TcpClient_T_Private::sigDisconnected, [=] {
    // 转发断开连接
    emit sigDisconnected();
  });
}

TcpClient_T::~TcpClient_T() {
  // 结束线程
  if (tcpClienPrivateThread_.isRunning()) {
    // 强行退出
    tcpClienPrivateThread_.terminate();
    // 尝试等待1秒
    tcpClienPrivateThread_.wait(1000);
  }

  // 释放等待
  waitDataTrans_->wakeAll();
  delete waitDataTrans_;
  // 释放锁
  delete waitDataTransMutex_;

  // 释放
  p_->deleteLater();
}

void TcpClient_T::bind(const QHostAddress &address, quint16 port) {
  return p_->bind(address, port);
}

void TcpClient_T::connectToHost(const QHostAddress &address, quint16 port) {
  return p_->connectToHost(address, port);
}

void TcpClient_T::start() {
  // 启动线程
  tcpClienPrivateThread_.start();
  // 转入线程
  p_->moveToThread(&tcpClienPrivateThread_);

  // p_启动
  emit sigStart();
}

void TcpClient_T::read(std::function<void(const QByteArray &)> f) {
  // 记录处理用的回调函数
  p_->readCall(std::move(f));
}

bool TcpClient_T::isConnected() {
  return p_->isConnected();
}

void TcpClient_T::write(const QByteArray &arg) {
  // 写入数据
  emit sigWrite(arg);
}

void TcpClient_T::writeAsync(const QByteArray &arg) {
  // 写入数据
  emit sigWrite(arg);

  // 等待数据写入完成
  waitDataTransMutex_->lock();
  waitDataTrans_->wait(waitDataTransMutex_);
  waitDataTransMutex_->unlock();
}

void TcpClient_T::write(char *ptr, int size) {
  // 设置当前为繁忙状态,保证数据的安全
  p_->setIsBusy(true);
  // 写入数据
  emit sigWritePtr(ptr, size);
}

void TcpClient_T::writeAsync(char *ptr, int size) {
  // 写入数据
  emit sigWritePtr(ptr, size);

  // 等待数据写入完成
  waitDataTransMutex_->lock();
  waitDataTrans_->wait(waitDataTransMutex_);
  waitDataTransMutex_->unlock();
}

const QHostAddress &TcpClient_T::localAddress() const {
  return p_->localAddress();
}

quint16 TcpClient_T::localPort() const {
  return p_->localPort();
}

QHostAddress TcpClient_T::peerAddress() const {
  return p_->peerAddress();
}

quint16 TcpClient_T::peerPort() const {
  return p_->peerPort();
}

bool TcpClient_T::isBusy() {
  return p_->isBusy();
}
